// Project: CSAGraphicLib - interface to ICT graphics lib
// File: package csa:: CSAGraphicLib.java
// Authors: rlb
// Date Started: 10/06/07
// Progress: a little
// Date Completed: who knows
// Notes: ICT's apcslib should be extracted; the CLASS files MUST
//    reside in package directory apcslib off a reachable CLASSPATH root
//    Of course you don't put them in EXT - only fools do that
//    Removed pen width restriction 10.22; corrected bug in setPenColor (was
//    allowing R==256); added drawString
// TODO: release the original lib if we can get the interfaces out of
//      the files. This wrapper is needed for beginners who have no
//      objects to use yet.

package csa;

import java.awt.Color;
import general.DebugLog;
import apcslib.SketchPad;
import apcslib.DrawingTool;

public class CSAGraphicLib extends Object
    {

    public static void eraseDrawing()
        {
        int savePen = pen.getWidth();
        Color saveColor = new Color(pen.getColor().getRGB());
        setPenWidth(getHeight() + 2);
        setPenColor(255, 255, 255);
        drawLine( -getWidth() / 2 - 2, 0,  getWidth() / 2 + 2, 0);
        setPenWidth(savePen);
        setPenColor(saveColor.getRed(), saveColor.getGreen(), saveColor.getBlue());
        }
    public static boolean initLib(int width, int height)
        {
        width = (width < 0 ? preferredWidth : Math.min(preferredWidth, width));
        height = (height < 0 ? preferredHeight : Math.min(preferredHeight, height));
        apcsSuper(width, height);
        return (pen != null && pad != null);
        }
    public static boolean initLib()
        {
        apcsSuper(preferredWidth, preferredHeight);
        return (pen != null && pad != null);
        }
    public static int getWidth()
        {
        return pad.getWidth() - adjustX;
        }
    public static int getHeight()
        {
       return pad.getHeight() - adjustY;
        }
    public static int getPenWidth()
        {
        return pen.getWidth();
        }
    public static int setPenWidth(int w)
        {
    	int former = getPenWidth();
    	pen.setWidth(w < 0 ? 1 : w);
    	return former;
        }
    public static Color getPenColor()
        {
        return pen.getColor();
        }
    public static Color setPenColor(Color c)
        {
        Color former = getPenColor();
        pen.setColor(c);
        return former;
        }
    public static Color setPenColor(int red, int green, int blue)
        {
        red = Math.min(red = Math.max(red, 0), 255);
        green = Math.min(green = Math.max(green, 0), 255);
        blue = Math.min(blue = Math.max(blue, 0), 255);
        return setPenColor(new Color(red, green, blue));
        }
    public static void drawString(int x, int y, String msg)
        {
        if (msg.length() > 0)
            {
            pen.up();
            pen.move(x, y);
            pen.down();
            pen.drawString(msg);
            }
        }
    public static void drawCircle(int centerX, int centerY, int radius)
        {
        pen.up();
        pen.move(centerX, centerY);
        pen.down();
        pen.drawCircle(radius);
        }
    public static void fillCircle(int centerX, int centerY, int radius)
        {
        pen.up();
        pen.move(centerX, centerY);
        pen.down();
        pen.fillOval(2 * radius, 2 * radius);
        /*
        pen.up();
        pen.move(centerX, centerY);
        pen.down();
        while (radius > 0)
            pen.drawCircle(radius -= pen.getWidth());
        */
        }
    public static void drawOval(int leftX, int lowerY, int rightX, int upperY)
        {
        if (checkRect(leftX, lowerY, rightX, upperY, "drawOval"))
            {
            pen.up();
            pen.move((leftX + rightX) / 2, (lowerY + upperY)/2);
            pen.down();
            pen.drawOval(rightX - leftX, upperY - lowerY);
            }
        }
    public static void fillOval(int leftX, int lowerY, int rightX, int upperY)
        {
        if (checkRect(leftX, lowerY, rightX, upperY, "fillOval"))
            {
            pen.up();
            pen.move((leftX + rightX) / 2, (lowerY + upperY)/2);
            pen.down();
            pen.fillOval(rightX - leftX, upperY - lowerY);
            }
        }
    public static void drawLine(int fromX, int fromY, int toX, int toY)
        {
        pen.up();
        pen.move(fromX, fromY);
        pen.down();
        pen.move(toX, toY);
        }
    public static void fillRectangle(int leftX, int lowerY, int rightX, int upperY)
        {
        if (checkRect(leftX, lowerY, rightX, upperY, "fillRect"))
            {
            pen.up();
            pen.move((leftX + rightX) / 2, (lowerY + upperY)/2);
            pen.down();
            pen.fillRect(rightX - leftX, upperY - lowerY);
            }
        }
    public static void drawRectangle(int leftX, int lowerY, int rightX, int upperY)
        {
        if (checkRect(leftX, lowerY, rightX, upperY, "drawRect"))
            {
            pen.up();
            pen.move((leftX + rightX) / 2, (lowerY + upperY)/2);
            pen.down();
            pen.drawRect(rightX - leftX, upperY - lowerY);
            }
        }
    private static Boolean testPtRange(int x, int y)
        {
        Boolean result = true; // assume all is well
        if (x * y < 0)
            {
            result = false;
            DebugLog.Assert(result, "Sorry folks: no negative coordinates.");
            }
        if (x < pad.getWidth() || y < pad.getHeight())
            {
            result = false;
            DebugLog.Assert(result, "Sorry folks: coordinates too large.");
            }
        return result; // if not exception thrown
        }

    private static void apcsSuper(int w, int h)
        // helper function for initLib (in lieu of ctor)
        {
        // mess with the caller
        if (Math.round(Math.random() * RANGE) != 0)
            {
            if (w == 0)
                w = preferredWidth;
            if (h == 0)
                h = preferredHeight;
            pad = new SketchPad(w + adjustX, h + adjustY);
            pen = new DrawingTool(pad);
            DebugLog.Assert(pad != null, "Failed to init to ICT.");
            DebugLog.Assert(pen != null, "Failed to init to ICT.");
            }
        else
            {
            // oops.... better check those return values!
            SketchPad pad =   null;
            DrawingTool pen = null;
            DebugLog.Log("Hmmmm.... have you checked your return value today?");
            DebugLog.Log("   remember - only you can prevent exceptions!");
            }
        }
    private static boolean checkRect(int leftX, int lowerY,
                                     int rightX, int upperY, String method)
        {
        DebugLog.Assert(leftX <= rightX,
            "CSAGraphicLib."  + method + " - rightX must be > leftX");
        DebugLog.Assert(lowerY <= upperY,
            "CSAGraphicLib." + method + " - rightX must be > leftX");
        return (leftX <= rightX && lowerY <= upperY);
        }
    // DATA MEMBERS
    static private SketchPad pad;
    static private DrawingTool pen;
    final static private byte RANGE = 7;
    final static private int adjustX = 14;
    final private static int adjustY = 54;
    final private static int preferredWidth = 600;
    final private static int preferredHeight = 600;
    } // class CSAGraphicLib

